package com.unis.service.system.impl;

import com.unis.common.constant.Constants;
import com.unis.common.util.ObjectReflect;
import com.unis.model.system.Code;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.unis.mapper.system.CodeMapper;
import com.unis.service.system.CodeService;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <pre>
 * @see CodeService
 * </pre>
 *
 * @author xuk
 * @version 1.0
 * @since 2018-12-29
 */
@Service("codeService")
public class CodeServiceImpl  implements CodeService {
	private static final Logger logger = LoggerFactory.getLogger(CodeServiceImpl.class);
    @Autowired
    private CodeMapper codeMapper;

    @Autowired
    private CacheManager cacheManager;

	@Override
    public List<Code> queryDictMap(@Param("zddm") String zddm){
    	return codeMapper.selectDictMap(zddm);
	}

	@Override
	public List<Map<String,Object>> selectTreeListByZddm(String zddm, String sjdm,int codeLevel) {
    	List<Map<String,Object>> list = null;
		Cache cache = cacheManager.getCache(Constants.ENCACHE_POOL);
		list = cache.get("all_"+zddm+"_"+(StringUtils.isNotBlank(sjdm)?sjdm:codeLevel),List.class);
		if (list==null){
			list = codeMapper.selectTreeListByZddm(zddm, sjdm);//上级代码为空时，默认条件为codeLevel = 1
			if (list!=null && list.size()>0){
				for(Map<String,Object> map : list){
					if (map.get("isParent")!=null && StringUtils.isNotBlank(map.get("isParent").toString())&& StringUtils.equalsIgnoreCase("true",map.get("isParent").toString())){
						map.put("nodes",this.selectTreeListByZddm(zddm,map.get("dm").toString(),0));
					}
				}
			}
			cache.put("all_"+zddm+"_"+(StringUtils.isNotBlank(sjdm)?sjdm:codeLevel),list);
		}

    	return  list;
	}

	@Override
	public List<Code> queryCodeList(Code code) {
		List<Code> list = null;
		list = codeMapper.select(code);
		return  list;
	}
	@Override
	public List<Map<String, Object>> queryListByZddm(String zddm, String dm, String filterSql) {
		List<Map<String,Object>> list = null;
		Cache cache = cacheManager.getCache(Constants.ENCACHE_POOL);
		list = cache.get("all_"+zddm+"_"+(StringUtils.isNotBlank(dm)?dm:"")+(StringUtils.isNotBlank(filterSql)?"_"+filterSql:""),List.class);
		if (list==null){
			list = codeMapper.selectListByZddm(zddm, dm,filterSql);
			cache.put("all_"+zddm+"_"+(StringUtils.isNotBlank(dm)?dm:"")+(StringUtils.isNotBlank(filterSql)?"_"+filterSql:""),list);
		}

		return  list;
	}

	@Override
	public Map<String, Map<String, String>> queryDicWithSpecCode(String... codes) throws Exception {
		Map<String, Map<String, String>> resDictMap =  new ConcurrentHashMap<String, Map<String, String>>();
		Cache cache = cacheManager.getCache(Constants.ENCACHE_POOL);

		for (String zddm : codes){
			Map<String,String> dicMap = cache.get(zddm,Map.class);
			if (dicMap == null){
				List<Code> codeList = this.queryDictMap(zddm);
				if (codeList!=null && codeList.size()>0){
					Map<String, String> procDictMap = new ConcurrentHashMap<String, String>();

					for (Code code : codeList){
						procDictMap.put(code.getDm(),code.getMc());
					}

					cache.put(zddm,procDictMap);
				}
			}
			if (cache.get(zddm,Map.class)==null){
				logger.error("该字典内容为空："+zddm);
				continue;
			}else {
				resDictMap.put(zddm,cache.get(zddm,Map.class));
			}
		}
		return resDictMap;
	}

	@Override
	public List<Object> translateList(List<Object> list,Class<?> clazz, String... fieldAndCodes) {
    	if (list!=null && !list.isEmpty() && list.size()>0 && fieldAndCodes!=null && fieldAndCodes.length>0){
			for (Object obj : list){
				this.translateObject(obj,clazz,fieldAndCodes);
			}
		}
		return list;
	}

	@Override
	public Object translateObject(Object obj, Class<?> clazz, String... fieldAndCodes) {
    	if (obj!=null && fieldAndCodes!=null && fieldAndCodes.length>0){
			String[][] fieldsAndCodes = getFieldAndCodes(fieldAndCodes);

			Map<String, Map<String, String>> dicMap = null;
			try {
				dicMap = this.queryDicWithSpecCode(fieldsAndCodes[1]);
			} catch (Exception e) {
				e.printStackTrace();
			}

			for (int i=0;i<fieldAndCodes.length;i++){
				try {
					Object fieldValue = ObjectReflect.getGetMethod(obj,fieldsAndCodes[0][i]);
					if (fieldValue!=null){
						String tranValue = dicMap.get(fieldsAndCodes[1][i]).get(fieldValue);
						ObjectReflect.setValue(obj,clazz,fieldsAndCodes[0][i],String.class,StringUtils.isNotBlank(tranValue)?tranValue:fieldValue);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return obj;
	}

	@Override
	public Map translateMap(Map map, String... fieldAndCodes) {
		if (map!=null && !map.isEmpty() && map.size()>0 && fieldAndCodes!=null && fieldAndCodes.length>0){
			String[][] fieldsAndCodes = getFieldAndCodes(fieldAndCodes);

			Map<String, Map<String, String>> dicMap = null;
			try {
				dicMap = this.queryDicWithSpecCode(fieldsAndCodes[1]);
			} catch (Exception e) {
				e.printStackTrace();
			}
			for (int i=0;i<fieldAndCodes.length;i++){
				Object fieldValue = map.get(fieldsAndCodes[0][i]);
				if (fieldValue!=null) {
					String tranValue = dicMap.get(fieldsAndCodes[1][i]).get(fieldValue);
					map.put(fieldsAndCodes[0][i], StringUtils.isNotBlank(tranValue) ? tranValue : fieldValue);
				}
			}
		}
		return map;
	}

	@Override
	public List<Map> translateListMap(List<Map> list, String... fieldAndCodes) {
		if (list!=null && !list.isEmpty() && list.size()>0 && fieldAndCodes!=null && fieldAndCodes.length>0){
			for (Map map : list){
				this.translateMap(map,fieldAndCodes);
			}
		}
		return list;
	}

	private String[][] getFieldAndCodes(String... fieldAndCodes){
		String[] codes = new String[fieldAndCodes.length];
		String[] fields = new String[fieldAndCodes.length];
		String[] fieldArray = null;
		for (int i=0;i<fieldAndCodes.length;i++){
			String fieldAndCode = fieldAndCodes[i];
			if (StringUtils.isNotBlank(fieldAndCode)){
				fieldArray = StringUtils.split(fieldAndCode,":");
				if (fieldArray!=null && fieldArray.length==2){
					fields[i] = fieldArray[0];
					codes[i] = fieldArray[1];
				}
			}
		}
		return new String[][]{fields,codes};
	}

}
